home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / amiga / hdf / hdf.lha / DFAN.C < prev    next >
Encoding:
C/C++ Source or Header  |  1980-02-06  |  42.6 KB  |  1,271 lines

  1. /***************************************************************************
  2. *
  3. *
  4. *                         NCSA HDF version 3.2r2
  5. *                            October 30, 1992
  6. *
  7. * NCSA HDF Version 3.2 source code and documentation are in the public
  8. * domain.  Specifically, we give to the public domain all rights for future
  9. * licensing of the source code, all resale rights, and all publishing rights.
  10. *
  11. * We ask, but do not require, that the following message be included in all
  12. * derived works:
  13. *
  14. * Portions developed at the National Center for Supercomputing Applications at
  15. * the University of Illinois at Urbana-Champaign, in collaboration with the
  16. * Information Technology Institute of Singapore.
  17. *
  18. * THE UNIVERSITY OF ILLINOIS GIVES NO WARRANTY, EXPRESSED OR IMPLIED, FOR THE
  19. * SOFTWARE AND/OR DOCUMENTATION PROVIDED, INCLUDING, WITHOUT LIMITATION,
  20. * WARRANTY OF MERCHANTABILITY AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE
  21. *
  22. ****************************************************************************
  23. */
  24.  
  25. #ifdef RCSID
  26. static char RcsId[] = "@(#)$Revision: 1.3 $";
  27. #endif
  28. /*
  29. $Header: /hdf/hdf/v3.2r2/src/RCS/dfan.c,v 1.3 1992/10/23 00:14:11 koziol beta koziol $
  30.  
  31. $Log: dfan.c,v $
  32.  * Revision 1.3  1992/10/23  00:14:11  koziol
  33.  * Changed all DFIstr*() and DFImem*() calls to HDstr*() and HDmem*() calls
  34.  * #ifdef'd out the macros Jason defined for Hopen, Hclose, etc. for Vsets
  35.  * Replaced Vset VFREESPACE and VGETSPACE calls with actual calls to HDfreespace
  36.  * and HDgetspace
  37.  * Added a MS-Windows lower lower for file I/O (which may not be completely working
  38.  *
  39.  * Revision 1.1  1992/08/25  21:40:44  koziol
  40.  * Initial revision
  41.  *
  42. */
  43. /*-----------------------------------------------------------------------------
  44.  * File:    dfan.c
  45.  * Purpose: read and write annotations: labels and descriptions of data items
  46.  * Invokes: df.c
  47.  * Contents: 
  48.  *
  49.  *  DFANgetlablen: get length of label of tag/ref
  50.  *  DFANgetlabel:  get label of tag/ref
  51.  *  DFANgetdesclen: get length of description of tag/ref
  52.  *  DFANgetdesc:   get description of tag/ref
  53.  *
  54.  *  DFANgetfidlen: get length of file ID
  55.  *  DFANgetfid:    get file ID
  56.  *  DFANgetfdslen: get length of file description
  57.  *  DFANgetfds:    get file description
  58.  *
  59.  *  DFANputlabel:  put label of tag/ref
  60.  *  DFANputdesc:   put description of tag/ref
  61.  *
  62.  *  DFANaddfid:    add file ID
  63.  *  DFANaddfds:    add file description
  64.  *
  65.  *  DFANlastref:   return ref of last annotation read or written
  66.  *  DFANlablist:   get list of labels for a particular tag
  67.  *
  68.  *  DFANIopen:     open/reopen file
  69.  *  DFANIlocate:   return ref of label/desc of tag/ref
  70.  *  DFANIaddentry: add entry in annotation directory
  71.  *  DFANIgetannlen: get length of annotation of tag/ref
  72.  *  DFANIgetann:   get annotation of tag/ref
  73.  *  DFANIputann:   put annotation of tag/ref
  74.  *  DFANIlablist:  get list of labels for a particular tag
  75.  *
  76.  *  DFANIaddfann:  add file annotation (ID or description)
  77.  *  DFANIgetfannlen: get length of file annotation
  78.  *  DFANIgetfann:  get file annotation
  79.  *---------------------------------------------------------------------------*/
  80.  
  81. #include "hdf.h"
  82. #include "herr.h"
  83. #include "hfile.h"
  84. #include "dfan.h"
  85.  
  86. static uint16 Lastref = 0;             /* Last ref read/written */
  87. static uint16 Next_label_ref = 0;      /* Next file label ref to read/write */
  88. static uint16 Next_desc_ref = 0;       /* Next file desc ref to read/write */
  89.  
  90. static char Lastfile[DF_MAXFNLEN];          /* last file opened */
  91.  
  92. /* pointers to directories of object annotations */
  93. static DFANdirhead *DFANdir[2] = { NULL,          /* object labels       */
  94.                                    NULL           /* object descriptions */
  95.                                  };
  96. /*
  97. ** Prototypes for local functions
  98. */
  99.  
  100. #ifndef VMS
  101. PRIVATE int32 DFANIopen
  102.     PROTO((char *filename, intn access));
  103. #else /*VMS*/
  104. PRIVATE int32 _DFANIopen();
  105. #endif
  106.  
  107. #ifdef OLD_WAY
  108. uint16 DFANIlocate
  109.   PROTO((int32 file_id, int type, uint16 tag, uint16 ref));
  110.  
  111. int DFANIaddentry
  112.   PROTO((int type, uint16 annref, uint16 datatag, uint16 dataref));
  113.  
  114.  
  115. int32 DFANIgetannlen
  116.   PROTO((char *filename, uint16 tag, uint16 ref, int type));
  117.  
  118. int DFANIgetann
  119.   PROTO((char *filename, uint16 tag, uint16 ref, uint8 *ann,
  120.                 int32 maxlen, int type));
  121.  
  122. int DFANIputann
  123.   PROTO((char *filename, uint16 tag, uint16 ref, uint8 *ann, 
  124.      int32 annlen, int type));
  125.  
  126. int DFANIlablist
  127.   PROTO((char *filename, uint16 tag, uint16 reflist[], uint8 *labellist,
  128.      int listsize, int maxlen, int startpos, int isfortran));
  129.  
  130. int DFANIaddfann
  131.   PROTO((int32 file_id, char *ann, int32 annlen, int type));
  132.  
  133. int32 DFANIgetfannlen
  134.   PROTO((int32 file_id, int type, int isfirst));
  135.  
  136. int32 DFANIgetfann
  137.   PROTO((int32 file_id, char *ann, int32 maxlen, int type, int isfirst));
  138. #endif  /* OLD_WAY */
  139.  
  140.  
  141. /*-----------------------------------------------------------------------------
  142.  * HDF object (i.e. tag/ref) label and description input routines
  143.  *---------------------------------------------------------------------------*/
  144.  
  145. /*-----------------------------------------------------------------------------
  146.  * Name:    DFANgetlablen
  147.  * Purpose: get length of label of tag/ref
  148.  * Inputs:  filename: name of HDF file
  149.  *          tag, ref: tag/ref of item of which we want label
  150.  * Returns: length of label on success, -1 on failure with DFerror set
  151.  * Users:   HDF HLL users, utilities, other routines
  152.  * Invokes: DFANIgetannlen
  153.  *---------------------------------------------------------------------------*/
  154.  
  155. #ifdef PROTOTYPE
  156. int32 DFANgetlablen(char *filename, uint16 tag, uint16 ref)
  157. #else
  158. int32 DFANgetlablen(filename, tag, ref)
  159.     char *filename;
  160.     uint16 tag, ref;
  161. #endif
  162. {
  163.     return(DFANIgetannlen(filename, tag, ref, DFAN_LABEL));
  164. }
  165.  
  166.  
  167. /*-----------------------------------------------------------------------------
  168.  * Name:    DFANgetlabel
  169.  * Purpose: get label of tag/ref
  170.  * Inputs:  filename: name of HDF file
  171.  *          tag, ref: tag/ref of item of which we want label
  172.  *          label: space to return label in
  173.  *          maxlen: size of space to return label in
  174.  * Returns: 0 on success, -1 on failure with DFerror set
  175.  * Users:   HDF HLL users, utilities, other routines
  176.  * Invokes: DFANIgetann
  177.  *---------------------------------------------------------------------------*/
  178.  
  179. #ifdef PROTOTYPE
  180. int DFANgetlabel(char *filename, uint16 tag, uint16 ref, char *label,
  181.                  int32 maxlen)
  182. #else
  183. int DFANgetlabel(filename, tag, ref, label, maxlen)
  184. char *filename;
  185. uint16 tag, ref;
  186. char *label;
  187. int32 maxlen;
  188. #endif
  189. {
  190.     return(DFANIgetann(filename, tag, ref, (uint8 *)label, maxlen, DFAN_LABEL));
  191. }
  192.  
  193.  
  194. /*-----------------------------------------------------------------------------
  195.  * Name:    DFANgetdesclen
  196.  * Purpose: get length of description of tag/ref
  197.  * Inputs:  filename: name of HDF file
  198.  *          tag, ref: tag/ref of item of which we want description
  199.  * Returns: length of description on success, -1 on failure with DFerror set
  200.  * Users:   HDF HLL users, utilities, other routines
  201.  * Invokes: DFANIgetannlen
  202.  *---------------------------------------------------------------------------*/
  203.  
  204. #ifdef PROTOTYPE
  205. int32 DFANgetdesclen(char *filename, uint16 tag, uint16 ref)
  206. #else
  207. int32 DFANgetdesclen(filename, tag, ref)
  208. char *filename;
  209. uint16 tag, ref;
  210. #endif 
  211. {
  212.     return(DFANIgetannlen(filename, tag, ref, DFAN_DESC));
  213. }
  214.  
  215.  
  216. /*-----------------------------------------------------------------------------
  217.  * Name:    DFANgetdesc
  218.  * Purpose: get description of tag/ref
  219.  * Inputs:  filename: name of HDF file
  220.  *          tag, ref: tag/ref of item of which we want description
  221.  *          desc: space to return description in
  222.  *          maxlen: size of space to return description in
  223.  * Returns: 0 on success, -1 on failure with DFerror set
  224.  * Users:   HDF HLL users, utilities, other routines
  225.  * Invokes: DFANIgetann
  226.  *---------------------------------------------------------------------------*/
  227.  
  228. #ifdef PROTOTYPE
  229. int DFANgetdesc(char *filename, uint16 tag, uint16 ref, char *desc,
  230.                 int32 maxlen)
  231. #else
  232. int DFANgetdesc(filename, tag, ref, desc, maxlen)
  233. char *filename;
  234. uint16 tag, ref;
  235. char *desc;
  236. int32 maxlen;
  237. #endif 
  238. {
  239.     return(DFANIgetann(filename, tag, ref, (uint8 *)desc, maxlen, DFAN_DESC));
  240. }
  241.  
  242.  
  243. /*-----------------------------------------------------------------------------
  244.  * File ID and description input routines
  245.  *---------------------------------------------------------------------------*/
  246.  
  247. /*-----------------------------------------------------------------------------
  248.  * Name:    DFANgetfidlen
  249.  * Purpose: get length of next file ID
  250.  * Inputs:  file_id: pointer to HDF file
  251.  *          isfirst: 1: start with first one; 0: get length of next one
  252.  * Returns: On success: length of next file ID; On failure: -1, with DFerror set
  253.  * Users:   HDF HLL users, utilities, other routines
  254.  * Invokes: DFANIgetfannlen
  255.  *---------------------------------------------------------------------------*/
  256.  
  257. #ifdef PROTOTYPE
  258. int32 DFANgetfidlen(int32 file_id, int isfirst)
  259. #else
  260. int32 DFANgetfidlen(file_id, isfirst)
  261. int32 file_id;
  262. int isfirst;
  263. #endif 
  264. {
  265.      return ( DFANIgetfannlen(file_id, DFAN_LABEL, isfirst) );
  266. }
  267.  
  268.  
  269. /*-----------------------------------------------------------------------------
  270.  * Name:    DFANgetfid
  271.  * Purpose: get next file ID
  272.  * Inputs:  file_id: pointer to HDF file
  273.  *          id: label
  274.  *          maxlen: max allowable length for label
  275.  *          isfirst: 1: start with first one; 0: get next one
  276.  * Returns: On success: length of label; On failure: -1, with DFerror set
  277.  * Users:   HDF HLL users, utilities, other routines
  278.  * Invokes: DFANIgetfann
  279.  * Remarks: If maxlen not great enough, label is truncated to maxlen-1 chars
  280.  *---------------------------------------------------------------------------*/
  281.  
  282. #ifdef PROTOTYPE
  283. int32 DFANgetfid(int32 file_id, char *id, int32 maxlen, int isfirst)
  284. #else
  285. int32 DFANgetfid(file_id, id, maxlen, isfirst)
  286. int32 file_id;
  287. char *id;
  288. int32 maxlen;
  289. int isfirst;
  290. #endif 
  291. {
  292.      return ( DFANIgetfann(file_id, id, maxlen, DFAN_LABEL, isfirst) );
  293. }
  294.  
  295.  
  296.  
  297. /*-----------------------------------------------------------------------------
  298.  * Name:    DFANgetfdslen
  299.  * Purpose: get length of next file description
  300.  * Inputs:  file_id: pointer to HDF file
  301.  *          isfirst: 1: start with first one; 0: get length of next one
  302.  * Returns: On success: length of next file ID; On failure: -1, with DFerror set
  303.  * Users:   HDF HLL users, utilities, other routines
  304.  * Invokes: DFANIgetfannlen
  305.  *---------------------------------------------------------------------------*/
  306.  
  307. #ifdef PROTOTYPE
  308. int32 DFANgetfdslen(int32 file_id, int isfirst)
  309. #else
  310. int32 DFANgetfdslen(file_id, isfirst)
  311.     int32 file_id;
  312.     int isfirst;
  313. #endif 
  314. {
  315.      return ( DFANIgetfannlen(file_id, DFAN_DESC, isfirst) );
  316. }
  317.  
  318.  
  319. /*-----------------------------------------------------------------------------
  320.  * Name:    DFANgetfds
  321.  * Purpose: get next file description
  322.  * Inputs:  file_id: pointer to HDF file
  323.  *          desc: description
  324.  *          maxlen: max allowable length for description
  325.  *          isfirst: 1: start with first one; 0: get next one
  326.  * Returns: On success: length of description;
  327.  *          On failure: -1, with DFerror set
  328.  * Users:   HDF HLL users, utilities, other routines
  329.  * Invokes: DFANIgetfann
  330.  * Remarks: If maxlen not great enough, description is truncated to
  331.  *          maxlen-1 chars
  332.  *---------------------------------------------------------------------------*/
  333.  
  334. #ifdef PROTOTYPE
  335. int32 DFANgetfds(int32 file_id, char *desc, int32 maxlen, int isfirst)
  336. #else
  337. int32 DFANgetfds(file_id, desc, maxlen, isfirst)
  338. int32 file_id;
  339. char *desc;
  340. int32 maxlen;
  341. int isfirst;
  342. #endif 
  343. {
  344.     return ( DFANIgetfann(file_id, desc, maxlen, DFAN_DESC, isfirst) );
  345. }
  346.  
  347.  
  348.  
  349. /*-----------------------------------------------------------------------------
  350.  * HDF object (i.e. tag/ref) label and description output routines
  351.  *---------------------------------------------------------------------------*/
  352.  
  353. /*-----------------------------------------------------------------------------
  354.  * Name:    DFANputlabel
  355.  * Purpose: put label of tag/ref
  356.  * Inputs:  filename: name of HDF file
  357.  *          tag, ref: tag/ref of item of which this is the label
  358.  *          label: label to write to file
  359.  * Returns: 0 on success, -1 on failure with DFerror set
  360.  * Users:   HDF HLL users, utilities, other routines
  361.  * Invokes: DFANIputann
  362.  *---------------------------------------------------------------------------*/
  363.  
  364. #ifdef PROTOTYPE
  365. int DFANputlabel(char *filename, uint16 tag, uint16 ref, char *label)
  366. #else
  367. int DFANputlabel(filename, tag, ref, label)
  368. char *filename;
  369. uint16 tag, ref;
  370. char *label;
  371. #endif 
  372. {
  373.     return(DFANIputann(filename, tag, ref, (uint8 *)label,
  374.                 (int32)HDstrlen(label), DFAN_LABEL));
  375. }
  376.  
  377.  
  378. /*-----------------------------------------------------------------------------
  379.  * Name:    DFANputdesc
  380.  * Purpose: put description of tag/ref
  381.  * Inputs:  filename: name of HDF file
  382.  *          tag, ref: tag/ref of item of which this is the description
  383.  *          desc: description to write to file
  384.  *          desclen: length of description
  385.  * Returns: 0 on success, -1 on failure with DFerror set
  386.  * Users:   HDF HLL users, utilities, other routines
  387.  * Invokes: DFANIputann
  388.  *---------------------------------------------------------------------------*/
  389.  
  390. #ifdef PROTOTYPE
  391. int DFANputdesc(char *filename, uint16 tag, uint16 ref, char *desc,
  392.                 int32 desclen)
  393. #else
  394. int DFANputdesc(filename, tag, ref, desc, desclen)
  395. char *filename;
  396. uint16 tag, ref;
  397. char *desc;
  398. int32 desclen;
  399. #endif 
  400. {
  401.     return(DFANIputann(filename, tag, ref, (uint8 *)desc, desclen, DFAN_DESC));
  402. }
  403.  
  404.  
  405. /*-----------------------------------------------------------------------------
  406.  * File ID and description output routines
  407.  *---------------------------------------------------------------------------*/
  408.  
  409. /*-----------------------------------------------------------------------------
  410.  * Name:    DFANaddfid
  411.  * Purpose: add file file ID
  412.  * Inputs:  file_id: pointer to HDF file
  413.  *          id: ID to write to file
  414.  * Returns: 0 on success, -1 on failure with DFerror set
  415.  * Users:   HDF HLL users, utilities, other routines
  416.  * Invokes: DFANIadfile_idann
  417.  *---------------------------------------------------------------------------*/
  418.  
  419. #ifdef PROTOTYPE
  420. int DFANaddfid(int32 file_id, char *id)
  421. #else
  422. int DFANaddfid(file_id, id)
  423. int32 file_id;
  424. char *id;
  425. #endif 
  426. {
  427.     return ( DFANIaddfann(file_id, id, (int32)HDstrlen(id), DFAN_LABEL) );
  428. }
  429.  
  430.  
  431. /*-----------------------------------------------------------------------------
  432.  * Name:    DFANaddfds
  433.  * Purpose: add file file ID
  434.  * Inputs:  file_id: pointer to HDF file
  435.  *          desc: description to write to file
  436.  *          desclen: length of description
  437.  * Returns: 0 on success, -1 on failure with DFerror set
  438.  * Users:   HDF HLL users, utilities, other routines
  439.  * Invokes: DFANIadfile_idann
  440.  *---------------------------------------------------------------------------*/
  441.  
  442. #ifdef PROTOTYPE
  443. int DFANaddfds(int32 file_id, char *desc, int32 desclen)
  444. #else
  445. int DFANaddfds(file_id, desc, desclen)
  446. int32 file_id;
  447. char *desc;
  448. int32 desclen;
  449. #endif 
  450. {
  451.     return ( DFANIaddfann(file_id, desc, desclen, DFAN_DESC) );
  452. }
  453.  
  454.  
  455. /*-----------------------------------------------------------------------------
  456.  * Miscellaneous other routines
  457.  *---------------------------------------------------------------------------*/
  458.  
  459. /*-----------------------------------------------------------------------------
  460.  * Name:    DFANlastref
  461.  * Purpose: Return last ref written or read
  462.  * Inputs:  none
  463.  * Globals: Lastref
  464.  * Returns: ref on success, -1 on error with DFerror set
  465.  * Users:   HDF users, utilities, other routines
  466.  * Invokes: none
  467.  * Method:  return Lastref
  468.  * Remarks: none
  469.  *---------------------------------------------------------------------------*/
  470.  
  471. #ifdef PROTOTYPE
  472. uint16 DFANlastref(void)
  473. #else
  474. uint16 DFANlastref()
  475. #endif 
  476. {
  477.     return(Lastref);
  478. }
  479.  
  480.  
  481. /*-----------------------------------------------------------------------------
  482.  * Name:    DFANlablist
  483.  * Purpose: Return list of refs and labels for a given tag
  484.  * Inputs:  filename: name of HDF file
  485.  *          tag: tag to get list of refs and labels for
  486.  *          reflist: array to place refs in
  487.  *          labellist: array of strings to place labels in
  488.  *          listsize: size of ref and label lists
  489.  *          maxlen: maximum length allowed for label
  490.  *          startpos: beginning from the startpos'th entry, upto listsize
  491.  *              entries will be returned.
  492.  * Returns: number of entries on success, -1 on error with DFerror set
  493.  * Users:   HDF users, utilities, other routines
  494.  * Invokes: DFANIlablist
  495.  * Method:  call DFANIlablist
  496.  * Remarks: Revised 04/17/90 so that it returns all ref numbers for
  497.  *          the given tag, rather than just those that have labels.
  498.  *          Where there is no corresponding label, the position in
  499.  *          labellist is zero filled (C) or blank filled (Fortran).
  500.  *---------------------------------------------------------------------------*/
  501.  
  502. #ifdef PROTOTYPE
  503. int DFANlablist(char *filename, uint16 tag, uint16 reflist[], char *labellist,
  504.                 int listsize, int maxlen, int startpos)
  505. #else
  506. int DFANlablist(filename, tag, reflist, labellist, listsize, maxlen, startpos)
  507. char *filename;
  508. uint16 tag, reflist[];
  509. char *labellist;
  510. int listsize;
  511. int maxlen, startpos;
  512. #endif 
  513. {
  514.     return(DFANIlablist(filename, tag, reflist, (uint8 *)labellist, 
  515.                                             listsize, maxlen, startpos, 0));
  516. }
  517.  
  518.  
  519. /******************************************************************************/
  520. /*----------------------- Internal routines ---------------------------------*/
  521. /******************************************************************************/
  522.  
  523.  
  524. /*-----------------------------------------------------------------------------
  525.  * Name:    DFANIopen
  526.  * Purpose: open or reopen a file
  527.  * Inputs:  filename: name of file to open
  528.  *          access : access mode
  529.  * Returns: file pointer on success, NULL on failure with DFerror set
  530.  * Users:   HDF systems programmers, other DFP routines
  531.  * Invokes: DFopen
  532.  * Remarks: This is a hook for someday providing more efficient ways to
  533.  *          reopen a file, to avoid re-reading all the headers
  534.  *---------------------------------------------------------------------------*/
  535.  
  536. #ifdef PROTOTYPE
  537. PRIVATE int32 DFANIopen(char *filename, intn access)
  538. #else
  539. PRIVATE int32 DFANIopen(filename, access)
  540. char *filename;
  541. intn access;
  542. #endif 
  543. {
  544.  
  545.     int32 file_id;
  546.     DFANdirhead *p, *q;
  547.  
  548.         /* use reopen if same file as last time - more efficient */
  549.     if (HDstrncmp(Lastfile,filename,DF_MAXFNLEN) || (access==DFACC_CREATE)) {
  550.                                     /* treat create as different file */
  551.         file_id = Hopen(filename, access, 0); 
  552.         if (file_id == FAIL) 
  553.             return FAIL;
  554.  
  555.         for (p=DFANdir[0]; p!=NULL; p=q) {  /* free linked list space */
  556.             q = p->next;
  557.             HDfreespace(p);
  558.         }
  559.         for (p=DFANdir[1]; p!=NULL; p=q) {
  560.             q = p->next;
  561.             HDfreespace(p);
  562.         }
  563.         DFANdir[0] = DFANdir[1] = NULL;
  564.     }
  565.     else {
  566.         file_id = Hopen(filename, access, 0);
  567.         if (file_id == FAIL)
  568.             return FAIL;
  569.     }
  570.  
  571.     HIstrncpy(Lastfile, filename, DF_MAXFNLEN);
  572.         /* remember filename, so reopen may be used next time if same file */
  573.     return(file_id);
  574. }
  575.  
  576.  
  577. /*-----------------------------------------------------------------------------
  578.  * Name:    DFANIlocate
  579.  * Purpose: get ref of annotation of given data tag/ref
  580.  * Inputs:  file_id: pointer to HDF file
  581.  *          type: DFAN_LABEL for labels, DFAN_DESC for descriptions
  582.  *          tag, ref: tag/ref of item of which we want ref of annotation
  583.  * Returns: ref of annotation on success, 0 on failure with DFerror set
  584.  * Users:   DFANIgetann, DFANIputann, DFANIgetannlen
  585.  * Invokes: DFaccess, DFnumber, DFread, DFIfind
  586.  * Bugs:    When FORTRAN calls this routine with type "label", the string
  587.  *          returned is incorrect in length by one character
  588.  *---------------------------------------------------------------------------*/
  589.  
  590. #ifdef PROTOTYPE
  591. uint16 DFANIlocate(int32 file_id, int type, uint16 tag, uint16 ref)
  592. #else
  593. uint16 DFANIlocate(file_id, type, tag, ref)
  594. int32 file_id;
  595. int type;
  596. uint16 tag, ref;
  597. #endif 
  598. {
  599.     char *FUNC="DFANIlocate";
  600.     uint8 datadi[4];
  601.     int32 more_anns;
  602.     int32 aid;
  603.     int32 nanns, i;
  604.     uint16 anntag, annref=0;
  605.     DFANdirhead *p;
  606.     uint8 *ptr;
  607.     
  608.     HEclear();
  609.  
  610.     anntag =
  611.         (type==DFAN_LABEL) ?
  612.             DFTAG_DIL :
  613.             DFTAG_DIA;
  614.  
  615.         /* if no directory for this type of annotation, make one */
  616.     if (DFANdir[type]==NULL) { 
  617.         nanns = Hnumber(file_id, anntag); 
  618. #ifdef QAK
  619.         if (nanns < 0) return(0);
  620. #else
  621.         if (nanns == 0) return(0);
  622. #endif
  623.  
  624.            /* allocate directory space.  Note head struct includes 1 entry */
  625.         DFANdir[type] = (DFANdirhead *)
  626.                           HDgetspace(((uint32)sizeof(DFANdirhead) +
  627.                                       (nanns-1) * sizeof(DFANdirentry)));
  628.         DFANdir[type]->next = NULL;
  629.         DFANdir[type]->nentries = nanns;
  630.  
  631.             /* fill directory table */
  632.         aid = Hstartread(file_id, anntag, DFREF_WILDCARD);
  633.         if (aid == FAIL) {
  634.             Hendaccess(aid); return 0;
  635.         }
  636.         else
  637.             more_anns = SUCCEED;
  638.  
  639.         for (i=0; (i< nanns) && (more_anns != FAIL); i++) {
  640.  
  641.             if (FAIL == Hinquire(aid, (int32*)NULL, (uint16*)NULL, &annref,
  642.                                 (int32*)NULL, (int32*)NULL, (int32*)NULL, 
  643.                                 (int16*)NULL, (int16*)NULL) )
  644.                 return 0;
  645.             if ((int32)FAIL == Hread(aid, (int32) 4, datadi) )
  646.                 return 0;
  647.  
  648.                 /* get data tag/ref */
  649.             DFANdir[type]->entries[i].annref = annref;
  650.             ptr = (uint8 *)&(datadi[0]);
  651.             UINT16DECODE(ptr, DFANdir[type]->entries[i].datatag);
  652.             UINT16DECODE(ptr, DFANdir[type]->entries[i].dataref);
  653.  
  654.             more_anns = Hnextread(aid, anntag, DFREF_WILDCARD, DF_CURRENT);
  655.         }
  656.         Hendaccess(aid);
  657.     }
  658.     if (!tag) return(1);      /* used to generate directory without search */
  659.  
  660.         /* find annotation that goes with this tag/ref */
  661.     for (p=(DFANdirhead *)DFANdir[type]; p!=NULL; p=p->next)
  662.         for (i=0; i<p->nentries; i++)
  663.             if(p->entries[i].annref != 0)
  664.                 if ((p->entries[i].dataref==ref) && (p->entries[i].datatag==tag))
  665.                     return(p->entries[i].annref);
  666.     HERROR(DFE_NOMATCH);
  667.     return(0);
  668. }
  669.  
  670.  
  671. /*-----------------------------------------------------------------------------
  672.  * Name:    DFANIaddentry
  673.  * Purpose: add entry to annotation directory
  674.  * Inputs:  type: DFAN_LABEL for labels, DFAN_DESC for descriptions
  675.  *          annref: tag/ref of annotation
  676.  *          datatag, dataref: tag/ref of item of which this is annotation
  677.  * Returns: 0 on success, -1 on failure with DFerror set
  678.  * Users:   DFANIputann
  679.  * Invokes: none
  680.  *---------------------------------------------------------------------------*/
  681.  
  682. #ifdef PROTOTYPE
  683. int DFANIaddentry(int type, uint16 annref, uint16 datatag, uint16 dataref)
  684. #else
  685. int DFANIaddentry(type, annref, datatag, dataref)
  686. uint16 annref, datatag, dataref;
  687. int type;
  688. #endif 
  689. {
  690.     int32 i;
  691.     DFANdirhead *p, *q;
  692.     
  693.         /* move to last entry in list */
  694.     for (p=DFANdir[type]; (p!=NULL) && (p->next!=NULL); p=p->next)
  695.         ;
  696.  
  697.     if (p) {                                    /* not new list */
  698.         for (i=0; i<p->nentries; i++)                   /* check all entries */
  699.             if (p->entries[i].annref==0) {              /* empty slot */
  700.                 p->entries[i].annref = annref;          /* store entry */
  701.                 p->entries[i].datatag = datatag;
  702.                 p->entries[i].dataref = dataref;
  703.                 return(0);
  704.             }
  705.     }
  706.  
  707.         /* need new list or new node in list */
  708.         /* allocate directory space.  Note head struct includes 1 entry */
  709.     q = (DFANdirhead *) HDgetspace((uint32)sizeof(DFANdirhead) +
  710.                                 (DFAN_DEFENTRIES-1) * sizeof(DFANdirentry));
  711.     q->next = NULL;
  712.     q->nentries = DFAN_DEFENTRIES;
  713.     if (!p) DFANdir[type] = q;          /* set pointer to this new node */
  714.     else p->next = q;
  715.  
  716.         /* store entry */
  717.     q->entries[0].annref = annref;
  718.     q->entries[0].datatag = datatag;
  719.     q->entries[0].dataref = dataref;
  720.  
  721.     for (i=1; i<DFAN_DEFENTRIES; i++)       /* mark rest unused */
  722.         q->entries[i].annref = 0;
  723.  
  724.     return(0);
  725. }
  726.  
  727.  
  728. /*-----------------------------------------------------------------------------
  729.  * Name:    DFANIgetannlen
  730.  * Purpose: get length of annotation of tag/ref
  731.  * Inputs:  filename: name of HDF file
  732.  *          tag, ref: tag/ref of item of which we want annotation
  733.  *          type: DFAN_LABEL for labels, DFAN_DESC for descriptions
  734.  * Returns: length of annotation on success, -1 on failure with DFerror set
  735.  * Users:   HDF HLL users, utilities, other routines
  736.  * Invokes: DFANIopen, DFANIlocate, DFIerr, DFclose, DFIfind
  737.  *---------------------------------------------------------------------------*/
  738.  
  739. #ifdef PROTOTYPE
  740. int32 DFANIgetannlen(char *filename, uint16 tag, uint16 ref, int type)
  741. #else
  742. int32 DFANIgetannlen(filename, tag, ref, type)
  743. char *filename;
  744. uint16 tag, ref;
  745. int type;
  746. #endif 
  747. {
  748.     char *FUNC="DFANIgetannlen";
  749.     int32 file_id, annlength;
  750.     uint16 anntag, annref;
  751.  
  752.     HEclear();
  753.     if (!tag) { HERROR(DFE_BADTAG); return FAIL; }
  754.     if (!ref) { HERROR(DFE_BADREF); return FAIL; }
  755.  
  756.     file_id = DFANIopen(filename, DFACC_READ);
  757.     if (file_id == FAIL) return FAIL; 
  758.  
  759.         /* get ref of annotation of tag/ref */
  760.     annref = DFANIlocate(file_id, type, tag, ref);
  761.     if (annref==0) {
  762.         Hclose(file_id); return FAIL;
  763.     }
  764.     anntag = (type==DFAN_LABEL) ? DFTAG_DIL : DFTAG_DIA;    /* set type tag */
  765.  
  766.     annlength = Hlength(file_id,anntag,annref) - 4;  /* 4=len of data tag/ref */
  767.     if (annlength == FAIL) { 
  768.         Hclose(file_id); return FAIL; 
  769.     }
  770.     Lastref = annref;                       /* remember ref last accessed */
  771.     if (Hclose(file_id) == FAIL)            /* close file */
  772.         return FAIL;
  773.  
  774.     return(annlength);
  775. }
  776.  
  777.  
  778. /*-----------------------------------------------------------------------------
  779.  * Name:    DFANIgetann
  780.  * Purpose: get annotation of tag/ref
  781.  * Inputs:  filename: name of HDF file
  782.  *          tag, ref: tag/ref of item of which we want annotation
  783.  *          ann: space to return annotation in
  784.  *          maxlen: size of space to return annotation in
  785.  *          type: DFAN_LABEL for labels, DFAN_DESC for descriptions
  786.  * Returns: 0 on success, -1 on failure with DFerror set
  787.  * Users:   HDF HLL users, utilities, other routines
  788.  * Invokes: DFANIopen, DFANIlocate, DFIerr, DFclose, DFaccess, DFIfind, DFread
  789.  *---------------------------------------------------------------------------*/
  790.  
  791. #ifdef PROTOTYPE
  792. intn DFANIgetann(char *filename, uint16 tag, uint16 ref, uint8 *ann,
  793.                 int32 maxlen, int type)
  794. #else
  795. intn DFANIgetann(filename, tag, ref, ann, maxlen, type)
  796. char *filename;
  797. uint16 tag, ref;
  798. uint8 *ann;
  799. int32 maxlen;
  800. int type;
  801. #endif 
  802. {
  803.     char *FUNC="DFANIgetann";
  804.     int32 file_id, aid;
  805.     int32 annlen;
  806.     uint16 anntag, annref;
  807.     uint8 datadi[4];        /* to read in and discard data/ref! */
  808.  
  809.     HEclear();
  810.     if (!ann) { HERROR(DFE_BADPTR); return FAIL; }
  811.     if (!tag) { HERROR(DFE_BADTAG); return FAIL; }
  812.     if (!ref) { HERROR(DFE_BADREF); return FAIL; }
  813.  
  814.     file_id = DFANIopen(filename, DFACC_READ);
  815.     if (file_id == FAIL) return FAIL; 
  816.  
  817.         /* get annref and anntag of annotation of tag/ref */
  818.     annref = DFANIlocate(file_id, type, tag, ref);
  819.     if (annref==0) {
  820.         Hclose(file_id); return FAIL;
  821.     }
  822.     anntag = (type==DFAN_LABEL) ? DFTAG_DIL : DFTAG_DIA;
  823.  
  824.         /* find DD for that annotation */
  825.     aid = Hstartread(file_id, anntag, annref);
  826.     if (aid == FAIL) { 
  827.         Hendaccess(aid); Hclose(file_id); return FAIL;
  828.     }
  829.     if (FAIL == Hinquire(aid,(int32*)NULL,(uint16*)NULL,(uint16*)NULL, &annlen,
  830.                         (int32*)NULL, (int32*)NULL, (int16*)NULL, (int16*)NULL) ) { 
  831.         Hendaccess(aid); Hclose(file_id); return FAIL;
  832.     }
  833.     annlen -= 4;  /* first four bytes were tag/ref, so they don't count */
  834.  
  835.         /* check length, if not enough space, truncate annotation */
  836.         /* labels need space for null terminator, descriptions don't */
  837.     if (type == DFAN_LABEL) {
  838.         if (annlen > maxlen-1) annlen = maxlen-1;
  839.     } else {
  840.         if (annlen > maxlen) annlen = maxlen;
  841.     }
  842.  
  843.         /* read annotation */
  844.     if ((int32)FAIL == Hread(aid, (int32) 4, datadi)) { /* go past tag/ref */
  845.         Hendaccess(aid); Hclose(file_id); return FAIL;
  846.     }
  847.     if ((int32)FAIL == Hread(aid, annlen, ann)) {  /* read the annotation */
  848.         Hendaccess(aid); Hclose (file_id); return FAIL;
  849.     }
  850.     if (type == DFAN_LABEL)
  851.         ann[annlen] = '\0';                 /* terminate string properly */
  852.  
  853.     Lastref = annref;                       /* remember ref last accessed */
  854.     Hendaccess(aid);
  855.     return(Hclose(file_id));
  856. }
  857.  
  858.  
  859. /*-----------------------------------------------------------------------------
  860.  * Name:    DFANIputann
  861.  * Purpose: put annotation of tag/ref into file
  862.  * Inputs:  filename: name of HDF file
  863.  *          tag, ref: tag/ref of item of which this is the annotation
  864.  *          ann: annotation to write to file
  865.  *          annlen: length of annotation
  866.  *          type: DFAN_LABEL for labels, DFAN_DESC for descriptions
  867.  * Returns: 0 on success, -1 on failure with DFerror set
  868.  * Users:   HDF HLL users, utilities, other routines
  869.  * Invokes: DFANIopen, DFANIlocate, DFANIaddentry, DFIerr, DFclose, DFnewref,
  870.  *          DFaccess, DFwrite
  871.  *---------------------------------------------------------------------------*/
  872.  
  873. #ifdef PROTOTYPE
  874. intn DFANIputann(char *filename, uint16 tag, uint16 ref, uint8 *ann,
  875.                 int32 annlen, int type)
  876. #else
  877. intn DFANIputann(filename, tag, ref, ann, annlen, type)
  878. char *filename;
  879. uint16 tag, ref;
  880. uint8 *ann;
  881. int32 annlen;
  882. int type;
  883. #endif 
  884. {
  885.  
  886.     char *FUNC="DFANIputann";
  887.     int32 file_id, aid;
  888.     int newflag=0;
  889.     uint16 anntag, annref;
  890.     uint8 datadi[4];        /* to hold data tag/ref for writing */
  891.     uint8 *ptr;
  892.  
  893.     HEclear();
  894.     if (!ann) { HERROR(DFE_BADPTR); return FAIL; }
  895.     if (!tag) { HERROR(DFE_BADTAG); return FAIL; }
  896.     if (!ref) { HERROR(DFE_BADREF); return FAIL; }
  897.  
  898.     file_id = DFANIopen(filename, DFACC_RDWR);
  899.     if (file_id == 0) return FAIL;
  900.  
  901.     anntag = (type==DFAN_LABEL) ? DFTAG_DIL : DFTAG_DIA;
  902.  
  903.         /* check if this tag/ref already has this type of annotation */
  904.     annref = DFANIlocate(file_id, type, tag, ref);
  905.     if (annref==0) {
  906.         annref = Hnewref(file_id);
  907.         if (annref==0) { 
  908.             Hclose(file_id); return FAIL;
  909.         }
  910.         newflag = 1;            /* remember to add ann tag/ref to directory */
  911.     }
  912.     
  913.         /* put annotation */
  914.         /* Note: cannot use DFputelement because need to write data tag/ref */
  915.     aid = Hstartwrite(file_id, anntag, annref, annlen+4);
  916.     if (aid == FAIL) {
  917.         Hendaccess(aid); Hclose(file_id); return FAIL;
  918.     }
  919.  
  920.         /* write annotation */
  921.     ptr = (uint8 *)&(datadi[0]);    /* first, write the object's tag/ref */
  922.     UINT16ENCODE(ptr, tag);
  923.     UINT16ENCODE(ptr, ref);
  924.     if ((int32)FAIL == Hwrite(aid, (int32) 4, datadi)) {
  925.         Hclose(file_id); return FAIL; 
  926.     }
  927.     if ((int32)FAIL == Hwrite(aid, annlen, ann)) {  /* then write the annotation */
  928.         Hendaccess(aid); Hclose(file_id); return FAIL;
  929.     }
  930.  
  931.         /* put annotation tag/ref into directory if new */
  932.     if (newflag) {
  933.         if (FAIL == DFANIaddentry(type, annref, tag, ref)){
  934.             Hendaccess(aid); Hclose(file_id); return FAIL;
  935.         }
  936.     }
  937.  
  938.     Lastref = annref;                       /* remember ref last accessed */
  939.     Hendaccess(aid);
  940.     return (Hclose(file_id));
  941. }
  942.  
  943.  
  944. /*-----------------------------------------------------------------------------
  945.  * Name:    DFANIlablist
  946.  * Purpose: Return list of refs and labels for a given tag
  947.  * Inputs:  filename: name of HDF file
  948.  *          tag: tag to get list of refs and labels for
  949.  *          reflist: array to place refs in
  950.  *          labellist: array of strings to place labels in
  951.  *          listsize: size of ref and label lists
  952.  *          maxlen: maximum length allowed for label
  953.  *          startpos: position in list from which on to return listsize entries
  954.  *          isfortran: 0 if C, 1 if Fortran
  955.  * Returns: number of entries on success, -1 on error with DFerror set
  956.  * Users:   DFANlablist
  957.  * Invokes: DFANIopen, DFIerr, DFclose, DFANIlocate, DFaccess, DFread
  958.  * Method:  search directory
  959.  * Remarks: none
  960.  *---------------------------------------------------------------------------*/
  961.  
  962. #ifdef PROTOTYPE
  963. int DFANIlablist(char *filename, uint16 tag, uint16 reflist[], 
  964.          uint8 *labellist, int listsize, int maxlen, int startpos, 
  965.          int isfortran)
  966. #else
  967. int DFANIlablist(filename, tag, reflist, labellist, listsize, maxlen,
  968.                                                         startpos, isfortran)
  969. char *filename;
  970. uint16 tag, reflist[];
  971. uint8 *labellist;                       /* actually an array of strings */
  972. int listsize, maxlen, startpos, isfortran;
  973. #endif 
  974. {
  975.     char *FUNC="DFANIlablist";
  976.     int32 i;
  977.     int j, k;
  978.     int32 file_id, aid, len;
  979.     uint16 ref;
  980.     DFANdirhead *p;
  981.     uint8 *lp;                    /* pointer to label */
  982.     int nrefs;
  983.     uint8 labeldi[4];             /* to read in and discard data/ref */
  984.     
  985.     HEclear();
  986.  
  987.     if (!reflist || !labellist)  { 
  988.         HERROR(DFE_BADPTR); return FAIL; }
  989.     if (!tag) { 
  990.         HERROR(DFE_BADTAG); return FAIL; }
  991.  
  992.     file_id = DFANIopen(filename, DFACC_READ);
  993.     if (file_id == 0) return FAIL;
  994.  
  995.        /* clear labellist.  pad with blanks for Fortran; add null for C  */
  996.     if (isfortran)
  997.         for (i=0; i<(int32)maxlen*(int32)listsize; i++)
  998.             labellist[i] = ' ';
  999.     else
  1000.         for (i=0; i<(int32)maxlen*(int32)listsize; i++)
  1001.             labellist[i] = '\0';
  1002.  
  1003.         /* find all refs for this tag; store them in reflist */
  1004.  
  1005.     nrefs = Hnumber(file_id, tag);         /* how many times is tag in file? */
  1006.     if (nrefs == FAIL) {
  1007.         Hclose(file_id); return FAIL;
  1008.     }
  1009.  
  1010.     aid = Hstartread(file_id, tag, DFREF_WILDCARD);   /* set search for refs */
  1011.     if (aid == FAIL) {
  1012.         Hendaccess(aid); Hclose(file_id); return FAIL;
  1013.     }
  1014.  
  1015.     for ( i=0, j=0; i<nrefs && j<listsize; i++) {
  1016.         if (HQuerytagref(aid, (uint16*)NULL, &ref) == FAIL) {
  1017.             Hendaccess(aid); Hclose(file_id); return FAIL;
  1018.         }
  1019.         if (i >= startpos-1)
  1020.             reflist[j++] = ref;         /* store next ref in reflist */
  1021.         Hnextread(aid, tag, DFREF_WILDCARD, DF_CURRENT);
  1022.     }
  1023.     nrefs = j;
  1024.     Hendaccess(aid);
  1025.  
  1026.         /* get directory of all labels */
  1027.  
  1028.     if (DFANdir[DFAN_LABEL]==NULL) {          /* if no dir info create dir */
  1029.         if (0== DFANIlocate(file_id, DFAN_LABEL, 0, 0)){
  1030.             Hendaccess(aid); Hclose(file_id); return FAIL;
  1031.         }
  1032.     }
  1033.  
  1034.     lp = labellist;
  1035.  
  1036.        /* Look through all labels. Get those that correspond to the tag,
  1037.            and match them with corresponding tag/refs in the reflist.      */
  1038.  
  1039.     for (p = DFANdir[DFAN_LABEL]; p!=NULL; p=p->next) { /* for each ann dir */
  1040.         for (i=0; i<p->nentries; i++) {              /* for each tag in dir */
  1041.             if (p->entries[i].datatag==tag) {        /* if this tag==our tag */
  1042.  
  1043.                 aid = Hstartread(file_id, DFTAG_DIL, p->entries[i].annref);
  1044.                 if (aid == FAIL) {
  1045.                     Hendaccess(aid); Hclose(file_id); return FAIL;
  1046.                 }
  1047.                 if ((int32)FAIL == Hread(aid, (int32) 4, labeldi)) { /* data tag/ref */
  1048.                     Hendaccess(aid); Hclose(file_id); return FAIL;
  1049.                 }
  1050.                     /* look for corresponding ref in reflist */
  1051.                 for (k=0; k<nrefs && p->entries[i].dataref != reflist[k];k++)
  1052.                      ;
  1053.                 if (k < nrefs) {               /* if ref found */
  1054.  
  1055.                     lp = labellist + k*maxlen;      /* get pos to copy to */
  1056.  
  1057.                         /* note len on read may be too big, but OK for DFread */
  1058.                     len = Hread(aid, (int32) (maxlen-1), lp);
  1059.                     if (len == FAIL) { 
  1060.                         Hendaccess(aid); Hclose(file_id); return FAIL;
  1061.                     }
  1062.                         /* ret now contains actual length read */
  1063.                         /* pad with blanks for Fortran; add null for C */
  1064.                     if (isfortran) 
  1065.                         while (len++ < maxlen) lp[len] = ' ';
  1066.                     else 
  1067.                         lp[len] = '\0';
  1068.                 }
  1069.                 Hendaccess(aid);
  1070.             }
  1071.         }
  1072.     }
  1073.     if (FAIL == Hclose(file_id))       /* close file */
  1074.         return FAIL; 
  1075.     return(nrefs);
  1076. }
  1077.  
  1078.  
  1079. /*-----------------------------------------------------------------------------
  1080.  * Name:    DFANIaddfann
  1081.  * Purpose: add file annotation (file ID or file description)
  1082.  * Inputs:  file_id: pointer to HDF file
  1083.  *          ann: annotation to write to file
  1084.  *          annlen: length of annotation
  1085.  *          type: DFAN_LABEL for labels, DFAN_DESC for descriptions
  1086.  * Returns: 0 on success, -1 on failure with DFerror set
  1087.  * Users:   HDF HLL users, utilities, other routines
  1088.  * Invokes: HDF general purpose routines
  1089.  *---------------------------------------------------------------------------*/
  1090.  
  1091. #ifdef PROTOTYPE
  1092. int DFANIaddfann(int32 file_id, char *ann, int32 annlen, int type)
  1093. #else
  1094. int DFANIaddfann(file_id, ann, annlen, type)
  1095.     int32 file_id;
  1096.     char *ann;
  1097.     int32 annlen;
  1098.     int type;
  1099. #endif 
  1100. {
  1101.     char *FUNC="DFANIaddfann";
  1102.     uint16 anntag, annref;
  1103.  
  1104.     HEclear();
  1105.     if (!ann) { HERROR(DFE_BADPTR);  return FAIL; }
  1106.  
  1107.     anntag = (type==DFAN_LABEL) ? DFTAG_FID : DFTAG_FD;
  1108.  
  1109.     annref = Hnewref(file_id);
  1110.     if (annref==0) return FAIL;
  1111.  
  1112.         /* write out annotation */
  1113.     if (FAIL == Hputelement(file_id, anntag, annref, (uint8 *) ann, annlen) )
  1114.         return FAIL;
  1115.  
  1116.     Lastref = annref;         /* remember ref last accessed */
  1117.     return(0);
  1118. }
  1119.  
  1120.  
  1121. /*-----------------------------------------------------------------------------
  1122.  * Name:    DFANIgetfannlen
  1123.  * Purpose: get length of next file annotation (file ID or file description)
  1124.  * Inputs:  file_id: pointer to HDF file
  1125.  *          type: DFAN_LABEL for labels, DFAN_DESC for descriptions
  1126.  *          isfirst: 1: start with first one; 0: get next one
  1127.  * Returns: On success: length of annotation; On failure: -1, with DFerror set
  1128.  * Users:   HDF HLL users, utilities, other routines
  1129.  * Invokes: HDF general purpose routines
  1130.  *---------------------------------------------------------------------------*/
  1131.  
  1132. #ifdef PROTOTYPE
  1133. int32 DFANIgetfannlen(int32 file_id, int type, int isfirst)
  1134. #else
  1135. int32 DFANIgetfannlen(file_id, type, isfirst)
  1136. int32 file_id;
  1137. int type;
  1138. int isfirst;
  1139. #endif 
  1140. {
  1141.     char *FUNC="DFANIgetfannlen";
  1142.     uint16 anntag, annref;
  1143.     int32 aid;
  1144.     int32 length;
  1145.  
  1146.     HEclear();
  1147.  
  1148.     /* Identify tag for this "type" of access; determine which ref to key on. */
  1149.     if (type == DFAN_LABEL) {
  1150.         anntag = DFTAG_FID;
  1151.         annref = (isfirst == 1) ? DFREF_WILDCARD : Next_label_ref;
  1152.     } else {
  1153.         anntag = DFTAG_FD;
  1154.         annref = (isfirst == 1) ? DFREF_WILDCARD : Next_desc_ref;
  1155.     }
  1156.     aid = Hstartread(file_id, anntag, annref);
  1157.     if (aid == FAIL) {
  1158.         Hendaccess(aid); return FAIL;
  1159.     }
  1160.     if (FAIL == Hinquire(aid, (int32*)NULL, (uint16*)NULL, &annref, &length ,
  1161.                          (int32*)NULL, (int32*)NULL,  (int16*)NULL, (int16*)NULL)){
  1162.         Hendaccess(aid); return FAIL;
  1163.     }
  1164.     if (type == DFAN_LABEL)         /* prepare for next call */
  1165.         Next_label_ref = annref;
  1166.     else
  1167.         Next_desc_ref = annref;
  1168.  
  1169.     Hendaccess(aid);
  1170.     Lastref = annref;             /* remember ref last accessed */ 
  1171.  
  1172.     if (length >= 0)         /* (length == 0) => no length found */
  1173.         return length;
  1174.     else {
  1175.         HERROR(DFE_NOMATCH); 
  1176.         return FAIL;
  1177.     }
  1178. }
  1179.  
  1180. /*-----------------------------------------------------------------------------
  1181.  * Name:    DFANIgetfann
  1182.  * Purpose: get next file annotation (file ID or file description)
  1183.  * Inputs:  file_id: pointer to HDF file
  1184.  *          ann: annotation to write to file
  1185.  *          annlen: length of annotation
  1186.  *          maxlen: max allowable length for annotation
  1187.  *          type: DFAN_LABEL for labels, DFAN_DESC for descriptions
  1188.  *          isfirst: 1: start with first one; 0: get next one
  1189.  * Returns: On success: length of annotation; On failure: -1, with DFerror set
  1190.  * Users:   HDF HLL users, utilities, other routines
  1191.  * Invokes: HDF general purpose routines
  1192.  * Remarks: If maxlen not great enough, ann is truncated to maxlen-1 chars
  1193.  * Bugs:    If ref is high possible ref value, setting of Next_label_ref or
  1194.             Next_desc_ref behave unpredictably. 
  1195.  *---------------------------------------------------------------------------*/
  1196.  
  1197. #ifdef PROTOTYPE
  1198. int32 DFANIgetfann(int32 file_id, char *ann, int32 maxlen, int type,
  1199.                           int isfirst)
  1200. #else
  1201. int32 DFANIgetfann(file_id, ann, maxlen, type, isfirst)
  1202. int32 file_id;
  1203. char *ann;
  1204. int32 maxlen;
  1205. int type;
  1206. int isfirst;
  1207. #endif 
  1208. {
  1209.     char *FUNC="DFANIgetfann";
  1210.     uint16 anntag, annref;
  1211.     int32 length, aid;
  1212.  
  1213.     HEclear();
  1214.  
  1215.     if (!ann) {
  1216.         HERROR(DFE_BADPTR); return FAIL;
  1217.     }
  1218.     /* Identify tag for this "type" of access; determine which ref to key on. */
  1219.     if (type == DFAN_LABEL) {
  1220.         anntag = DFTAG_FID;
  1221.         annref = (isfirst == 1) ? DFREF_WILDCARD : Next_label_ref;
  1222.     } else {
  1223.         anntag = DFTAG_FD;
  1224.         annref = (isfirst == 1) ? DFREF_WILDCARD : Next_desc_ref;
  1225.     }
  1226.  
  1227.     aid = Hstartread(file_id, anntag, annref);
  1228.     if (aid == FAIL) {
  1229.         Hendaccess(aid); return FAIL;
  1230.     }
  1231.     if (FAIL == Hinquire(aid, (int32*)NULL, (uint16*)NULL, &annref, &length ,
  1232.                          (int32*)NULL, (int32*)NULL, (int16*)NULL, (int16*)NULL) ){
  1233.         Hendaccess(aid); return FAIL;
  1234.     }
  1235.     length = (length > maxlen) ?maxlen : length; /* truncate if too long */
  1236.  
  1237.     if ((int32)FAIL == Hread(aid, length, (uint8 *) ann) )    /* get the annotation */
  1238.         return FAIL;
  1239.  
  1240.     if(length > maxlen - 1) length = maxlen - 1;
  1241.  
  1242.     ann[length] = '\0';
  1243.  
  1244.     Lastref = annref;                          /* remember ref last accessed */ 
  1245.  
  1246.         /* prepare for next call */
  1247.     if (FAIL == Hnextread(aid, anntag, DFREF_WILDCARD, DF_CURRENT) )
  1248.     {                           /* If no more of them, set Next_ ???_ref */
  1249.         if (type == DFAN_LABEL) /*    to one higher than current value   */
  1250.             Next_label_ref++;   /*    so that next call will fail.       */ 
  1251.         else
  1252.             Next_desc_ref++;
  1253.     } else {                    /* Otherwise save the next ref */
  1254.         if (FAIL == Hinquire(aid, (int32*)NULL,(uint16*)NULL, &annref, 
  1255.                                   (int32*)NULL, (int32*)NULL, (int32*)NULL,  
  1256.                                   (int16*)NULL, (int16*)NULL) )  {
  1257.             Hendaccess(aid);
  1258.             return FAIL;
  1259.         }
  1260.         if (type == DFAN_LABEL)
  1261.             Next_label_ref = annref;
  1262.         else
  1263.             Next_desc_ref = annref;
  1264.     }
  1265.  
  1266.     Hendaccess(aid);
  1267.     return(length);                /* return length of label */
  1268. }
  1269.  
  1270.  
  1271.